﻿using GSPatEditor.Pat.Effect;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GSPatEditor.Pat
{
    static class EffectListExt
    {
        public static void RunList(this List<FilteredEffect> list, Simulator.Actor actor)
        {
            if (list == null)
            {
                return;
            }
            foreach (var e in list)
            {
                if (e.Filter != null && e.Filter.Simulate(actor) == false)
                {
                    continue;
                }
                e.Effect.Simulate(actor);
            }
        }

        public static bool Simulate(this List<FilterBase> filters, Simulator.Actor actor)
        {
            if (filters == null)
            {
                return true;
            }
            return filters.All(f => f.Simulate(actor));
        }
    }

    class NormalAction : Action
    {
        public List<FilteredEffect> InitEffect;
        public List<FilteredEffect> UpdateEffect;
        public List<FilteredEffect> HitEffect;
        public List<FilteredEffect>[] MotionEventEffect;

        public PatProject Project { get; private set; }

        public override void BeginAction(Simulator.Actor actor)
        {
            InitEffect.RunList(actor);
            actor.UpdateLabel = UpdateEffect.RunList;
            actor.HitEvent = HitEffect.RunList;
            if (MotionEventEffect != null)
            {
                actor.EndKeyFrameLabel =
                    MotionEventEffect
                    .Take(MotionEventEffect.Length - 1)
                    .Where(x => x != null)
                    .Select<List<FilteredEffect>, Simulator.ActorLabel>(x => x.RunList)
                    .ToArray();
                actor.EndMotionLabel = MotionEventEffect.Last().RunList;
            }
        }

        public override SystemActionType GetSystemActionType()
        {
            return SystemActionType.None;
        }
        
        private void SetupEffect(FilteredEffect effect)
        {
            if (effect.Filter != null)
            {
                foreach (var f in effect.Filter)
                {
                    f.Init(this);
                }
            }
            effect.Effect.Init(this);
        }

        public void SetupEffects(PatProject project)
        {
            this.Project = project;
            if (InitEffect != null)
            {
                foreach (var effect in InitEffect)
                {
                    SetupEffect(effect);
                }
            }
            if (UpdateEffect != null)
            {
                foreach (var effect in UpdateEffect)
                {
                    SetupEffect(effect);
                }
            }
            if (HitEffect != null)
            {
                foreach (var effect in HitEffect)
                {
                    SetupEffect(effect);
                }
            }
            if (MotionEventEffect != null)
            {
                foreach (var list in MotionEventEffect)
                {
                    foreach (var effect in list)
                    {
                        SetupEffect(effect);
                    }
                }
            }
        }
    }
}
